import axios from 'axios'
import { ElNotification } from 'element-plus'
import { getToken, removeToken } from '@/utils/auth'

const idempotentTokenCache = new Map()

// 生成请求内容的hash值
function generateRequestHash(config) {
  const { method, url, data, params } = config
  const requestData = {
    method: method?.toLowerCase(),
    url,
    data: data ? JSON.stringify(data) : '',
    params: params ? JSON.stringify(params) : ''
  }
  
  const str = JSON.stringify(requestData)
  let hash = 0
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i)
    hash = ((hash << 5) - hash) + char
    hash = hash & hash // 转换为32位整数
  }
  return Math.abs(hash).toString(36)
}

// 生成幂等性token
function generateIdempotentToken(config) {
  if (config.method?.toLowerCase() === 'get') return null

  const requestHash = generateRequestHash(config)
  const now = Date.now()
  const ttlMs = 5000

  const cached = idempotentTokenCache.get(requestHash)
  if (cached && (now - cached.timestamp) < ttlMs) {
    return cached.token // 复用同一个 token
  }

  const token = requestHash
  idempotentTokenCache.set(requestHash, { token, timestamp: now })

  // 清理过期
  for (const [k, v] of idempotentTokenCache.entries()) {
    if (now - v.timestamp >= ttlMs) idempotentTokenCache.delete(k)
  }
  return token
}

// 创建axios实例
const service = axios.create({
  baseURL: import.meta.env.VUE_APP_BASE_API || '', // api 的 base_url
  timeout: 30000, // 请求超时时间 30秒
  withCredentials: true // 携带Cookie/Session信息
})

// request拦截器
service.interceptors.request.use(
  config => {
    const token = getToken()
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}` // 让每个请求携带自定义token
    }

    // 只有非 GET 请求且没有手动设置 Content-Type 才设置默认值
    if (config.method && config.method.toLowerCase() !== 'get' && !config.headers['Content-Type']) {
      config.headers['Content-Type'] = 'application/json'
    }

    // 添加幂等token（只有非GET请求才添加）
    const idempotentToken = generateIdempotentToken(config)
    if (idempotentToken) {
      config.headers['Idempotent-Token'] = idempotentToken
    }

    return config
  },
  error => {
    Promise.reject(error)
  }
)

// response 拦截器
service.interceptors.response.use(
  response => {
    // 如果是blob响应，直接返回response.data
    if (response.config.responseType === 'blob') {
      return response.data
    }
    return response.data
  },
  error => {
    console.error('请求错误详情:', error)

    // 兼容blob下载出错json提示
    if (error.response?.data instanceof Blob && error.response.data.type.toLowerCase().indexOf('json') !== -1) {
      const reader = new FileReader()
      reader.readAsText(error.response.data, 'utf-8')
      reader.onload = function() {
        const errorMsg = JSON.parse(reader.result).message
        ElNotification.error({
          title: errorMsg,
          duration: 5000
        })
      }
    } else {
      let code = 0
      let errorMessage = '请求失败'

      try {
        code = error.response?.data?.status || error.response?.status
      } catch (e) {
        // 处理各种网络错误
        if (error.toString().indexOf('Error: timeout') !== -1) {
          errorMessage = '网络请求超时'
        } else if (error.toString().indexOf('ERR_NETWORK') !== -1) {
          errorMessage = '网络连接失败，请检查网络连接'
        } else if (error.toString().indexOf('ERR_CONNECTION_CLOSED') !== -1) {
          errorMessage = '服务器连接已关闭，请稍后重试'
        } else if (error.toString().indexOf('ERR_CONNECTION_REFUSED') !== -1) {
          errorMessage = '服务器拒绝连接，请检查服务器状态'
        } else if (error.code === 'ECONNABORTED') {
          errorMessage = '请求超时，请稍后重试'
        } else {
          errorMessage = '网络连接异常，请检查网络设置'
        }

        ElNotification.error({
          title: errorMessage,
          duration: 5000
        })
        return Promise.reject(error)
      }

      console.log('HTTP状态码:', code)
      if (code) {
        if (code === 401) {
          // 清除token并跳转到登录页
          removeToken()
          errorMessage = '登录已过期，请重新登录'
        } else if (code === 403) {
          errorMessage = '权限不足'
        } else if (code === 404) {
          errorMessage = '请求的资源不存在'
        } else if (code === 500) {
          errorMessage = '服务器内部错误'
        } else if (code >= 500) {
          errorMessage = '服务器错误，请稍后重试'
        } else {
          errorMessage = error.response?.data?.message || `请求失败 (${code})`
        }

        ElNotification.error({
          title: errorMessage,
          duration: 5000
        })
      } else {
        // 没有HTTP状态码的情况，通常是网络问题
        ElNotification.error({
          title: errorMessage,
          duration: 5000
        })
      }
    }
    return Promise.reject(error)
  }
)
export default service

